View Javadoc

1   // ExceptionDeliverer.java, created Mon Feb  5 23:23:21 2001 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Runtime;
5   
6   import joeq.Allocator.CodeAllocator;
7   import joeq.Class.PrimordialClassLoader;
8   import joeq.Class.jq_Class;
9   import joeq.Class.jq_CompiledCode;
10  import joeq.Class.jq_Method;
11  import joeq.Class.jq_Reference;
12  import joeq.Class.jq_StaticMethod;
13  import joeq.Class.jq_TryCatch;
14  import joeq.Debugger.OnlineDebugger;
15  import joeq.Memory.CodeAddress;
16  import joeq.Memory.StackAddress;
17  import joeq.Scheduler.jq_Thread;
18  import joeq.UTF.Utf8;
19  import jwutil.strings.Strings;
20  import jwutil.util.Assert;
21  
22  /*
23   * @author  John Whaley <jwhaley@alum.mit.edu>
24   * @version $Id: ExceptionDeliverer.java 1941 2004-09-30 03:37:06Z joewhaley $
25   */
26  public abstract class ExceptionDeliverer {
27  
28      public static /*final*/ boolean TRACE = false;
29      
30      public static void abstractMethodError() throws AbstractMethodError {
31          SystemInterface.debugwriteln("Unimplemented abstract method!");
32          throw new AbstractMethodError();
33      }
34      
35      public static void nativeMethodError() throws LinkageError {
36          SystemInterface.debugwriteln("Unimplemented native method!");
37          throw new LinkageError();
38      }
39      
40      public static void athrow(Throwable k) {
41          CodeAddress ip = (CodeAddress) StackAddress.getBasePointer().offset(StackAddress.size()).peek();
42          StackAddress fp = (StackAddress) StackAddress.getBasePointer().peek();
43          ExceptionDeliverer.deliverToCurrentThread(k, ip, fp);
44          Assert.UNREACHABLE();
45      }
46      
47      public static void trap_handler(int code) {
48          switch (code) {
49              case 0: throw new NullPointerException();
50              case 1: throw new ArrayIndexOutOfBoundsException();
51              case 2: throw new ArithmeticException();
52              case 3: throw new StackOverflowError();
53              default: throw new InternalError("unknown hardware exception type: "+code);
54          }
55      }
56      public static void debug_trap_handler(int code) {
57          boolean pass = OnlineDebugger.debuggerEntryPoint();
58          if (pass) {
59              SystemInterface.debugwriteln(">>> Passing on exception code "+code);
60              trap_handler(code);
61              Assert.UNREACHABLE();
62          }
63      }
64      
65      public abstract void deliverToStackFrame(jq_CompiledCode cc, Throwable x, jq_TryCatch tc, CodeAddress ip, StackAddress fp);
66      public abstract Object getThisPointer(jq_CompiledCode cc, CodeAddress ip, StackAddress fp);
67      
68      public static void deliverToCurrentThread(Throwable x, CodeAddress ip, StackAddress fp) {
69          jq_Thread t = Unsafe.getThreadBlock();
70          Assert._assert(t != null && !t.is_delivering_exception);
71          t.is_delivering_exception = true;
72          
73          jq_Class x_type = (jq_Class) jq_Reference.getTypeOf(x);
74          if (TRACE) SystemInterface.debugwriteln("Delivering exception of type "+x_type+" to ip="+ip.stringRep()+" fp="+fp.stringRep());
75          for (;;) {
76              jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
77              if (TRACE) SystemInterface.debugwriteln("Checking compiled code "+cc);
78              if ((cc == null) || (fp.isNull())) {
79                  // reached the top!
80                  System.out.println("Exception in thread \""+Unsafe.getThreadBlock()+"\" "+x);
81                  x.printStackTrace(System.out);
82                  t.is_delivering_exception = false;
83                  SystemInterface.die(-1);
84                  Assert.UNREACHABLE();
85                  return;
86              } else {
87                  jq_TryCatch tc = cc.findCatchBlock(ip, x_type);
88                  if (tc != null) {
89                      CodeAddress address = (CodeAddress) cc.getStart().offset(tc.getHandlerEntry());
90                      
91                      // go to this catch block!
92                      if (TRACE) SystemInterface.debugwriteln("Jumping to catch block at "+address.stringRep());
93                      t.is_delivering_exception = false;
94                      cc.deliverException(tc, fp, x);
95                      Assert.UNREACHABLE();
96                      return;
97                  }
98                  if (cc.getMethod() != null && cc.getMethod().isSynchronized()) {
99                      // need to perform monitorexit here.
100                     Object o;
101                     if (cc.getMethod().isStatic()) {
102                         o = Reflection.getJDKType(cc.getMethod().getDeclaringClass());
103                         if (TRACE) SystemInterface.debugwriteln("Performing monitorexit on static method "+cc.getMethod()+": object "+o);
104                     } else {
105                         o = cc.getThisPointer(ip, fp);
106                         if (TRACE) SystemInterface.debugwriteln("Performing monitorexit on instance method "+cc.getMethod()+": object "+o.getClass()+"@"+Strings.hex(System.identityHashCode(o)));
107                     }
108                     Monitor.monitorexit(o);
109                 }
110                 ip = (CodeAddress) fp.offset(StackAddress.size()).peek();
111                 fp = (StackAddress) fp.peek();
112             }
113         }
114     }
115     
116     public static void printStackTrace(Object backtrace, java.io.PrintWriter pw) {
117         StackFrame sf = (StackFrame)backtrace;
118         while (sf.next != null) {
119             CodeAddress ip = sf.ip;
120             jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
121             String s;
122             if (cc != null) {
123                 jq_Method m = cc.getMethod();
124                 int code_offset = ip.difference(cc.getStart());
125                 if (m != null) {
126                     Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
127                     int bc_index = cc.getBytecodeIndex(ip);
128                     int line_num = m.getLineNumber(bc_index);
129                     s = "\tat "+m+" ("+sourcefile+":"+line_num+" bc:"+bc_index+" off:"+Strings.hex(code_offset)+")";
130                 } else {
131                     s = "\tat <unknown cc> (start:"+cc.getStart().stringRep()+" off:"+Strings.hex(code_offset)+")";
132                 }
133             } else {
134                 s = "\tat <unknown addr> (ip:"+ip.stringRep()+")";
135             }
136             pw.println(s.toCharArray());
137             sf = sf.next;
138         }
139     }
140 
141     public static void printStackTrace(Object backtrace, java.io.PrintStream pw) {
142         StackFrame sf = (StackFrame)backtrace;
143         while (sf.next != null) {
144             CodeAddress ip = sf.ip;
145             jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
146             String s;
147             if (cc != null) {
148                 jq_Method m = cc.getMethod();
149                 int code_offset = ip.difference(cc.getStart());
150                 if (m != null) {
151                     Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
152                     int bc_index = cc.getBytecodeIndex(ip);
153                     int line_num = m.getLineNumber(bc_index);
154                     s = "\tat "+m+" ("+sourcefile+":"+line_num+" bc:"+bc_index+" off:"+Strings.hex(code_offset)+")";
155                 } else {
156                     s = "\tat <unknown cc> (start:"+cc.getStart().stringRep()+" off:"+Strings.hex(code_offset)+")";
157                 }
158             } else {
159                 s = "\tat <unknown addr> (ip:"+ip.stringRep()+")";
160             }
161             pw.println(s.toCharArray());
162             sf = sf.next;
163         }
164     }
165     
166     public static void printStackTrace(Object backtrace) {
167         StackFrame sf = (StackFrame)backtrace;
168         while (sf.next != null) {
169             CodeAddress ip = sf.ip;
170             jq_CompiledCode cc = CodeAllocator.getCodeContaining(ip);
171             String s;
172             if (cc != null) {
173                 jq_Method m = cc.getMethod();
174                 int code_offset = ip.difference(cc.getStart());
175                 if (m != null) {
176                     Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
177                     int bc_index = cc.getBytecodeIndex(ip);
178                     int line_num = m.getLineNumber(bc_index);
179                     s = "\tat "+m+" ("+sourcefile+":"+line_num+" bc:"+bc_index+" off:"+Strings.hex(code_offset)+")";
180                 } else {
181                     s = "\tat <unknown cc> (start:"+cc.getStart().stringRep()+" off:"+Strings.hex(code_offset)+")";
182                 }
183             } else {
184                 s = "\tat <unknown addr> (ip:"+ip.stringRep()+")";
185             }
186             SystemInterface.debugwriteln(s);
187             sf = sf.next;
188         }
189     }
190     
191     public static Object getStackTrace() {
192         // stack traces are a linked list.
193         CodeAddress ip = (CodeAddress) StackAddress.getBasePointer().offset(StackAddress.size()).peek();
194         StackAddress fp = (StackAddress) StackAddress.getBasePointer().peek();
195         StackFrame sf = new StackFrame(fp, ip);
196         sf.fillInStackTrace();
197         return sf;
198     }
199     
200     public static class StackFrame {
201         protected StackAddress fp; // location of this stack frame
202         protected CodeAddress ip;  // ip address
203         protected StackFrame next; // next frame in linked list
204         
205         public StackFrame(StackAddress fp, CodeAddress ip) {
206             this.fp = fp; this.ip = ip;
207         }
208         
209         public void fillInStackTrace() {
210             StackFrame dis = this;
211             while (!dis.fp.isNull()) {
212                 CodeAddress ip2 = (CodeAddress) dis.fp.offset(StackAddress.size()).peek();
213                 StackAddress fp2 = (StackAddress) dis.fp.peek();
214                 dis.next = new StackFrame(fp2, ip2);
215                 dis = dis.next;
216             }
217         }
218 
219         public int getSize() {
220             StackFrame p = this; int s = 0;
221             while (p != null) {
222                 p = p.next; ++s;
223             }
224             return s;
225         }
226         public StackFrame getNext() { return next; }
227         public StackAddress getFP() { return fp; }
228         public CodeAddress getIP() { return ip; }
229         
230         public String toString() {
231             return CodeAllocator.getCodeContaining(ip)+" ip="+ip.stringRep()+" fp="+fp.stringRep();
232         }
233     }
234     
235     public static final jq_Class _class;
236     public static final jq_StaticMethod _athrow;
237     public static final jq_StaticMethod _trap_handler;
238     public static final jq_StaticMethod _debug_trap_handler;
239     public static final jq_StaticMethod _abstractMethodError;
240     public static final jq_StaticMethod _nativeMethodError;
241     static {
242         _class = (jq_Class)PrimordialClassLoader.loader.getOrCreateBSType("Ljoeq/Runtime/ExceptionDeliverer;");
243         _athrow = _class.getOrCreateStaticMethod("athrow", "(Ljava/lang/Throwable;)V");
244         _trap_handler = _class.getOrCreateStaticMethod("trap_handler", "(I)V");
245         _debug_trap_handler = _class.getOrCreateStaticMethod("debug_trap_handler", "(I)V");
246         _abstractMethodError = _class.getOrCreateStaticMethod("abstractMethodError", "()V");
247         _nativeMethodError = _class.getOrCreateStaticMethod("nativeMethodError", "()V");
248     }
249 }